//
// Created by cube on 2020/10/24.
//

#include "UdpPool.h"


int UdpPool::send(const NetAddress &addr, int8_t *data, const uint32_t &len) {
    auto l = __udps.lock_guard();
    if(__udps.empty())__udps[NetAddress()] = Base::net_socket(AF_INET,SOCK_DGRAM,0);

    __send_udp_index++;
    if(__send_udp_index >= __udps.size())__send_udp_index = 0;
    uint64_t index = __send_udp_index;
    auto p = __udps.begin();
    std::advance(p,index);

    return NetBase::Base::net_sendto(p->second,data,len,0,&addr.getAddr(),sizeof(addr.getAddr()));
}

void UdpPool::bind(const NetAddress &addr) {
    auto l = __udps.lock_guard();
    if(__udps.contains(addr))return;
    NetUdp udp;
    if(udp.bind(addr)){
        addSocket(udp.getSocket());
        __udps.insert(std::pair(addr,udp.getSocket()));
    }else{
        //error
    }
}

void UdpPool::ubind(const NetAddress &addr) {
    auto l = __udps.lock_guard();
    if(!__udps.contains(addr))return;
    NetUdp& udp = udp_socket();
    udp.setSocket(__udps.at(addr));
    eraseSocket(udp.getSocket());
    __udps.erase(addr);
    udp.close();
}

void UdpPool::close() {
    auto l = __udps.lock_guard();
    Multplex::close();
    for(auto p : __udps)NetBase::Base::net_close(p.second);
    __udps.clear();
}

bool UdpPool::read(int socket) {
    NetUdp& udp = udp_socket();
    udp.setSocket(socket);
    NetAddress& addr = udp.getAddr();
    int rul = read_from_io(udp,addr);
    return rul >= 0;
}

NetUdp& UdpPool::udp_socket() {
    thread_local NetUdp udp(-1);
    return udp;
}

//
//class MMM : public UdpPool{
//public:
//    using UdpPool::UdpPool;
//protected:
//    int read_from_io(NetUdp& udp,NetAddress& addr) override {
//        char buf[1024] = {};
//        int rul = udp.recv(addr,(int8_t*)buf,sizeof(buf));
//        std::cout<<"read  "<<udp.getSocket()<<"  "<<buf<<std::endl;
//        std::string send_buf = "hello client. im server ";
//        send(addr,(int8_t*)send_buf.data(),send_buf.size());
//        return rul;
//    }
//};
//
//
//int main(int argc, char *argv[])
//{
//    std::cout<<"start"<<std::endl;
//
//    MMM udps(10);
//    udps.bind(NetAddress("127.0.0.1",8822));
//    udps.bind(NetAddress("127.0.0.1",8811));
//    udps.bind(NetAddress("127.0.0.1",8833));
//    std::thread t([&](){
//        while (udps.server() != -1);
//    });
//    udps.unBind(NetAddress("127.0.0.1",8833));
//    t.join();
//
//    std::cout<<"end"<<std::endl;
//    return 0;
//}